(ns scripts.cljmon.agent.server
  (:use scripts.cljmon.query)
  (:use web.json-rpc)
  (:use compojure.core
        ring.adapter.jetty))

(def ^:dynamic *sessions* (atom {}))

(defn- remove-timedout []
  (let [timestamp (System/currentTimeMillis)]
    (swap! *sessions*
      (fn [state]
        (into {}
          (for [[id s] state :when (not (> (- timestamp (:timestamp s)) (* 60 60 1000)))] ; expiration: 1 hour
            [id s]))))))

(defn register-query [session-id expr]
  (let [{:keys [queries pdh? winapi?]} (read-string expr)
        session (create-query-session {:pdh? pdh? :winapi? winapi?})]
    (session
      (fn []
        (let [queries (translate-local-queries queries)
              comments (collect-local-comments queries)
              headers (collect-local-headers queries)
              timestamp (System/currentTimeMillis)]
          (swap! *sessions* assoc session-id {:session session
                                              :queries queries
                                              :timestamp timestamp})
          (remove-timedout)
          (pr-str {:comments comments :headers headers}))))))

(defn execute-query [session-id]
  (let [session (get @*sessions* session-id)
        timestamp (System/currentTimeMillis)]
    (when-not session
      (throw (Exception. (str "Session not found: " session-id))))
    (swap! *sessions* assoc session-id (assoc session :timestamp timestamp))
    (let [{:keys [session queries]} session]
      (session
        (fn []
          (pr-str (collect-local-data queries)))))))

(defn unregister-query [session-id]
  (swap! *sessions* dissoc session-id)
  nil)

(def apis {"register" register-query
           "query" execute-query
           "unregister" unregister-query
           "debug" (fn [] (pr-str @*sessions*))})

(defn api-call [method params]
  (if-let [f (get apis method)]
    (apply f params)
    (throw (Exception. (str "Unknown method " method)))))

(def json-rpc-apis (json-rpc api-call))

(defroutes web-routes
  (GET "/" []  "POST to /api/json-rpc")
  (POST "/api/json-rpc" []  json-rpc-apis))

(defn start-agent-server [port]
  (run-jetty web-routes {:port port}))



